# -*- coding: utf-8 -*-

from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
from django.contrib.admin.views.decorators import staff_member_required
from django.template import RequestContext
from django.http import HttpResponseRedirect, HttpResponseForbidden, Http404, \
    HttpResponse
from django.contrib.auth.models import User
from django.views.generic import list_detail
from nstat.traffic.models import Payment, UserProfile, TrafficCategory, Tariff, \
    PrepaidPacket
from django.core.urlresolvers import reverse
from django.contrib.auth.forms import PasswordChangeForm
from nstat.traffic.forms import PayForm, ChangeTariffForm, SelectChannelForm
import datetime, time
from django.db import transaction

def root(request):
    return HttpResponseRedirect(reverse('userinfo', args=(), 
        kwargs={"statuser": request.user.id}))

def payments(request, statuser=None):
    if statuser is None and not request.user.is_staff:
        return HttpResponseForbidden(u"Ты можешь смотреть только свою статистику")
    q = Payment.objects.all()
    if not statuser is None:
        q = q.filter(user=request.statuser.get_profile())
    return list_detail.object_list(
        request,
        queryset = q.select_related().order_by('-date'),
        template_name = "payments.html",
        template_object_name = "payments",
        paginate_by = 20)

@staff_member_required
def users(request):
    q = UserProfile.objects.all()
    return list_detail.object_list(
        request,
        queryset = q.select_related().order_by('-last_activity'),
        template_name = "users.html",
        template_object_name = "user",
        paginate_by = 20)

def password_change(request):
    post_change_redirect = reverse('userinfo', kwargs={'statuser': request.user.id})
    if request.method == "POST":
        form = PasswordChangeForm(request.user, request.POST)
        if form.is_valid():
            form.save()
            request.user.get_profile().update_key(form.cleaned_data["new_password1"])
            request.user.save()
            request.user.message_set.create(message=u"Пароль изменён")
            return HttpResponseRedirect(post_change_redirect)
    else:
        form = PasswordChangeForm(request.user)
    return render_to_response("password_change.html", {
            'form': form,
            }, context_instance=RequestContext(request))

@staff_member_required
@transaction.commit_on_success
def pay(request, statuser):
    """
    deadlock тут быть не может, т.к. блокируется только один объект
    """
    if request.method == "POST":
        form = PayForm(request.POST)
        if form.is_valid():
            profile_id = User.objects.get(id=statuser).get_profile().id
            puser = UserProfile.objects.select_for_update().get(id=profile_id)
            redirect = reverse('userinfo', kwargs={'statuser': statuser})
            puser.pay(amount=form.cleaned_data["sum"], \
                      cashier=request.user.get_profile(),
                      category=form.cleaned_data["category"], comment=\
                      form.cleaned_data["comment"])
            puser.check()
            request.user.message_set.create(message=u"Платёж произведён")
            return HttpResponseRedirect(redirect)
    else:
        form = PayForm()
    return render_to_response('pay.html', {'form': form, 
                              'puser': User.objects.get(id=statuser).get_profile(),
                              }, context_instance=RequestContext(request))


@staff_member_required
@transaction.commit_on_success
def change_tariff(request, statuser):
    """
    deadlock тут быть не может, т.к. блокируется только один объект
    """
    if request.method == "POST":
        form = ChangeTariffForm(request.POST)
        if form.is_valid():
            profile_id = User.objects.get(id=statuser).get_profile().id
            puser = UserProfile.objects.select_for_update().get(id=profile_id)
            redirect = reverse('userinfo', kwargs={'statuser': statuser})
            puser.change_tariff(tariff=form.cleaned_data["tariff"], clear=
                                form.cleaned_data["is_prepaid_dropped"])
            puser.check()
            request.user.message_set.create(message=u"Тариф изменён")
            return HttpResponseRedirect(redirect)
    else:
        form = ChangeTariffForm()
    return render_to_response('change_tariff.html', {'form': form,
                              'puser': User.objects.get(id=statuser).get_profile(),
                              }, context_instance=RequestContext(request))


@transaction.commit_on_success
def change_channel(request, statuser):
    """
    deadlock тут быть не может, т.к. блокируется только один объект
    """
    if request.method == "POST":
        form = SelectChannelForm(request.POST)
        if form.is_valid():
            profile_id = User.objects.get(id=statuser).get_profile().id
            puser = UserProfile.objects.select_for_update().get(id=profile_id)
            redirect = reverse('userinfo', kwargs={'statuser': statuser})
            puser.change_channel(channel=form.cleaned_data["channel"])
            puser.check()
            request.user.message_set.create(message=u"Канал изменён")
            return HttpResponseRedirect(redirect)
    else:
        form = SelectChannelForm()
    return render_to_response('change_channel.html', {'form': form,
                              'puser': User.objects.get(id=statuser).get_profile(),
                              }, context_instance=RequestContext(request))

@transaction.commit_on_success
def turn_inet(request, statuser, status):
    redirect = reverse('userinfo', kwargs={'statuser': statuser})
    profile_id = request.statuser.get_profile().id
    profile = UserProfile.objects.select_for_update().get(id=profile_id)
    profile.check()
    if profile.blocked:
        request.user.message_set.create(message=u"Недоступно")
    else:
        profile.turn_inet(status)
        if status: request.user.message_set.create(message=u"Включен")
        else: request.user.message_set.create(message=u"Отключен")
    return HttpResponseRedirect(redirect)

@transaction.commit_on_success
def turn_reserve(request, statuser, status):
    redirect = reverse('userinfo', kwargs={'statuser': statuser})
    profile_id = request.statuser.get_profile().id
    profile = UserProfile.objects.select_for_update().get(id=profile_id)
    profile.check()
    profile.turn_reserve(status)
    if status: request.user.message_set.create(message=u"Вы переключились на резервный канал")
    else: request.user.message_set.create(message=u"Вы переключились на основной канал")
    return HttpResponseRedirect(redirect)

def stats(request, statuser=None):
    """
    !!! uses raw SQL, not portable
    """
    if statuser is None and not request.user.is_staff:
        return HttpResponseForbidden(u"Ты можешь смотреть только свою статистику")

    try: year = int(request.GET["year"])
    except: year = None

    try: month = int(request.GET["month"])
    except: month = None

    try: day = int(request.GET["day"])
    except: day = None

    try: traffic_category = int(request.GET["category"])
    except: traffic_category = None

    from django.db import connection
    cursor = connection.cursor()

    if year:
        if month:
            if day: depth = 3
            else: depth = 2
        else: depth = 1
    else: depth = 0

    q = [year, month, day]

    parts = ["extract(year from date)", "extract(month from date)", \
            "extract(day from date)", "hour"]

    part = parts[depth]

    cond = " ".join([" and %s=%%s " % parts[i]  for i in range(depth)])

    params = q[:depth]

    if request.statuser:
            cond += " and user_id=%s "
            params.append(request.statuser.get_profile().id)

    query = """select traffic_category_id
            from traffic_trafficunit
            where 1=1
            %s
            group by traffic_category_id""" % (cond, )

    cursor.execute(query, params)

    categories = [TrafficCategory.objects.get(id=i) for (i, ) in cursor]
    
    if traffic_category:
            cond += " and traffic_category_id=%s "
            params.append(traffic_category)

    query = """select %s as part, sum(incoming), sum(outgoing),
            sum(incoming+outgoing), sum(cost)
            from traffic_trafficunit
            where 1=1
            %s
            group by part order by part""" % (part, cond)

    cursor.execute(query, params)

    if request.statuser: profile = request.statuser.get_profile()
    else: profile = None

    results = cursor.fetchall()

    max_total = max(total for p, _in, _out, total, cost in results) if results else 1

    return render_to_response('stats.html', {
            'results': results,
            'year': year,
            'month': month,
            'day': day,
            'category_id': traffic_category,
            'categories': categories,
            'depth': depth,
            'profile': profile,
            'max_total': max_total,
                              }, context_instance=RequestContext(request))


def help(request):
    tariffs = Tariff.objects.all()
    if not request.user.is_staff: tariffs = tariffs.filter(is_public=True)
    tariffs = tariffs.order_by("cost")
    return render_to_response('help.html', {
            'tariffs': tariffs,
                              }, context_instance=RequestContext(request))

@transaction.commit_on_success
def api(request):
    """
    буэ...
    но авторизатор переписывать нормально влом
    deadlock тут быть не может, т.к. блокируется только один объект
    """
    try: key = request.GET["skey"]
    except: return HttpResponseForbidden("403")
    try: user = UserProfile.objects.select_for_update().get(key=key)
    except UserProfile.DoesNotExist: return HttpResponseForbidden("403")
    try: inet = int(request.GET["inet"])
    except: inet = 0
    if inet:
        if inet>0:
            user.turn_inet(True, datetime.timedelta(seconds=inet))
        else:
            user.turn_inet(False)
    # user.save() # не нужно, так как turn_inet уже делает .save()
    if user.inet: status = "1"
    else: status = "0"
    try: packet = user.prepaidpacket_set.get(traffic_category__id=1).prepaid
    except PrepaidPacket.DoesNotExist: packet=0
    return HttpResponse("%s %s %0.2f %s %s %d %s %s %0.2f %d" % ( \
        user.user.username, user.user.email, user.balance, user.ip, status, \
        time.mktime(user.last_activity.timetuple()), user.tariff.id, \
        0, user.credit, packet))
